package de.suur.jarmi.gson;

import java.io.Serializable;
import java.lang.reflect.Type;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import de.suur.jarmi.common.Request;

public class RequestAdapter implements JsonSerializer<Request>,
		JsonDeserializer<Request> {

	private static final String METHOD_NAME = "methodName";
	private static final String PARAMETER_TYPES = "parameterTypes";
	private static final String PARAMETERS = "parameters";
	private static final String SERVICE_CLASS = "serviceClass";

	@Override
	public Request deserialize(JsonElement json, Type typeOfT,
			JsonDeserializationContext context) throws JsonParseException {
		try {
			JsonObject jsonObject = json.getAsJsonObject();

			String methodName = jsonObject.get(METHOD_NAME).getAsString();

			Class<?> serviceClass = Class.forName(jsonObject.get(SERVICE_CLASS)
					.getAsString());

			JsonArray jsonParameterTypes = jsonObject.get(PARAMETER_TYPES)
					.getAsJsonArray();
			Class<?>[] parameterTypes = new Class<?>[jsonParameterTypes.size()];
			for (int i = 0; i < jsonParameterTypes.size(); i++) {
				parameterTypes[i] = Class.forName(jsonParameterTypes.get(i)
						.getAsString());
			}

			JsonArray jsonParameters = jsonObject.get(PARAMETERS)
					.getAsJsonArray();
			Serializable[] parameters = new Serializable[jsonParameters.size()];
			for (int i = 0; i < jsonParameters.size(); i++) {
				parameters[i] = context.deserialize(jsonParameters.get(i),
						parameterTypes[i]);
			}

			return new Request(serviceClass, methodName, parameters,
					parameterTypes);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public JsonElement serialize(Request src, Type typeOfSrc,
			JsonSerializationContext context) {
		JsonObject jsonObject = new JsonObject();
		jsonObject.addProperty(METHOD_NAME, src.getMethodName());
		jsonObject.addProperty(SERVICE_CLASS, src.getServiceClass().getName());
		jsonObject.add(PARAMETERS, context.serialize(src.getParameters()));
		JsonArray jsonArray = new JsonArray();
		for (Class<?> clazz : src.getParameterTypes()) {
			jsonArray.add(new JsonPrimitive(clazz.getName()));
		}
		jsonObject.add(PARAMETER_TYPES, jsonArray);
		return jsonObject;
	}

}
